package cn.lingyangwl.agile.food.core.manager;

import cn.hutool.core.collection.CollectionUtil;
import cn.lingyangwl.agile.food.core.mapper.*;
import cn.lingyangwl.agile.food.model.entity.*;
import cn.lingyangwl.agile.model.constants.*;
import cn.lingyangwl.agile.tenant.core.utils.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 商品属性值 仓储层
 *
 * @author shenguangyang
 */
@Slf4j
@Repository
public class GoodsAttributeValueManager extends ServiceImpl<GoodsAttributeValueMapper, GoodsAttributeValue>
    implements IService<GoodsAttributeValue> {
    @Resource
    private GoodsAttributeMapper attributeMapper;

    public void saveAttributeValue(List<GoodsAttribute> attributeList, Long goodsId) {
        this.remove(GoodsAttributeValue.lqw().eq(GoodsAttributeValue::getGoodsId, goodsId));
        List<GoodsAttributeValue> attributeValueList = attributeList.stream()
            .flatMap(e ->
                e.getValues().stream().map(GoodsAttribute.Values::getName).distinct().map(name -> {
                    GoodsAttributeValue item = new GoodsAttributeValue();
                    item.setGoodsId(goodsId).setGoodsAttributeId(e.getId()).setValue(name);
                    return item;
                }
            )).collect(Collectors.toList());
        this.saveBatch(attributeValueList);
    }

    public List<GoodsAttribute> listAttributeValue(Long goodsId) {
        if (Objects.isNull(goodsId)) {
            return Collections.emptyList();
        }

        // 查询当前租户所有属性
        Map<Long, GoodsAttribute> attributeMap = TenantUtils.execute(DataIsolateLevel.MAIN, () -> {
            LambdaQueryWrapper<GoodsAttribute> lqw = GoodsAttribute.lqw();
            return attributeMapper.selectList(lqw).stream()
                .collect(Collectors.toMap(GoodsAttribute::getId, Function.identity()));
        });

        Map<Long, List<GoodsAttributeValue>> map = this.list(GoodsAttributeValue.lqw().eq(GoodsAttributeValue::getGoodsId, goodsId))
            .stream().collect(Collectors.groupingBy(GoodsAttributeValue::getGoodsAttributeId));

        List<GoodsAttribute> resp = new ArrayList<>();
        for (Map.Entry<Long, List<GoodsAttributeValue>> entry : map.entrySet()) {
            GoodsAttribute attribute = attributeMap.get(entry.getKey());
            if (Objects.isNull(attribute)) {
                continue;
            }
            List<String> goodsAttrValueList = entry.getValue().stream().map(GoodsAttributeValue::getValue)
                .collect(Collectors.toList());

            List<GoodsAttribute.Values> values = attribute.getValues().stream()
                .filter(e -> goodsAttrValueList.contains(e.getName())).collect(Collectors.toList());

            GoodsAttribute respAttribute = new GoodsAttribute();
            BeanUtils.copyProperties(attribute, respAttribute);
            respAttribute.setValues(values);
            resp.add(respAttribute);
        }
        return resp;
    }

    public boolean exitAttributeValue(Long attributeId, Set<String> attributeValues) {
        if (CollectionUtil.isEmpty(attributeValues)) {
            return false;
        }
        LambdaQueryWrapper<GoodsAttributeValue> lqw = GoodsAttributeValue.lqw()
            .eq(GoodsAttributeValue::getGoodsAttributeId, attributeId)
            .in(GoodsAttributeValue::getValue, attributeValues);
        return this.count(lqw) > 0;
    }

    public boolean exitByAttributeId(List<Long> attributeIds) {
        if (CollectionUtil.isEmpty(attributeIds)) {
            return false;
        }
        LambdaQueryWrapper<GoodsAttributeValue> lqw = GoodsAttributeValue.lqw()
            .in(GoodsAttributeValue::getGoodsAttributeId, attributeIds);
        return this.count(lqw) > 0;
    }

    public List<GoodsAttributeValue> listByGoodsId(Long goodsId) {
        return this.list(GoodsAttributeValue.lqw().eq(GoodsAttributeValue::getGoodsId, goodsId));
    }

    public void batchDeleteByGoodsIds(List<Long> goodsIds) {
        if (CollectionUtil.isEmpty(goodsIds)) {
            return;
        }
        this.remove(GoodsAttributeValue.lqw().in(GoodsAttributeValue::getGoodsId, goodsIds));
    }
}
